import {
  Component,
  OnInit,
  ViewEncapsulation,
  ChangeDetectionStrategy,
  Input,
  Output,
  EventEmitter,
  ChangeDetectorRef,
  OnChanges,
  SimpleChanges,
  AfterViewInit,
  OnDestroy,
} from '@angular/core';
import { coerceNumberProperty } from '@angular/cdk/coercion';
import { Subject } from 'rxjs';
import { takeUntil, distinctUntilChanged, filter } from 'rxjs/operators';
import { InputNumber, InputBoolean, LvConfig, TypeUtils } from '../core/api';
import { OptionItem } from '../select/api';
import { PageConfig } from './interface';

@Component({
  selector: 'lv-paginator',
  templateUrl: './paginator.component.html',
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: {
    '[class.lv-paginator]': 'true',
    '[class.disabled]': 'lvDisabled',
    '[class.lv-paginator-simple]': '_pageSimpleMode',
    '[class.lv-paginator-default]': '!_pageSimpleMode',
    // NEED_DO '[dir]': 'lvDir'
  },
})
export class PaginatorComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {
  // 输入输出属性
  @Input() @InputNumber() lvPageIndex = 0; // 当前页数
  @Input() @InputBoolean() lvDisabled = false; // 是否为禁用状态
  @Input() @InputBoolean() lvShowTotal = true; // 是否显示总页数
  @Input() @InputBoolean() lvShowQuickjump = true; // 是否显示跳转器
  @Input() @InputBoolean() lvShowSelected = false; // 是否显示选中条数
  @Input() lvMode: 'default' | 'simple' = 'default'; // 分页器模式：默认、简单
  @Input() @InputBoolean() lvShowPageSizeOptions = true; // 是否显示每页条数选择下拉
  @Input() lvHideOnSinglePage: boolean | number = false;
  @Output() lvPageChange = new EventEmitter<PageConfig>();
  @Input() @InputNumber() lvPageSize = LvConfig.paginatorOptions.lvPageSize; // 每页条数
  // NEED_DO @Input() lvDir: 'ltr' | 'rtl' = 'ltr';
  @Input() lvPanelClass: string | string[] | Set<string> | { [key: string]: any };
  previewNum = 2; // current 前后显示页码个数(2个)
  _codeNumber = 5; // 连续码数
  renderEndNum = 0;
  renderStartNum = 0;
  panelClass: string;

  _total: number = 0;

  _overPageIndex = 7; // 默认超过7页有。。。
  showPagination = true;
  _selected: number = 0;
  _pages: number[] = []; // 所有页数的列表-simple
  // 内部变量
  _initFlag: boolean = false;
  _pageSizeOptions: number[];
  _renderPages: number[] = []; // 展示的所有页数列表-default
  language = LvConfig.language;

  _pageSizeList: number[] = [];
  _defaultPageSize: number = 5;
  // 外部可访问变量
  pagesOption: OptionItem[] = [];
  pageSizeListOption: OptionItem[];
  totalChange$ = new Subject<number>(); // 记录total变化
  private _destroy$ = new Subject<void>();
  constructor(private _cdr: ChangeDetectorRef) {}
  get lvTotal(): number {
    return this._total;
  }

  get lvSelected(): number {
    return this._selected;
  }

  get _isFirstIndex(): boolean {
    return this.lvPageIndex === 0;
  }

  // 展示的页码
  get _showedPageIndex(): number {
    return this.lvPageIndex + 1;
  }

  get _pageSimpleMode(): boolean {
    return this.lvMode === 'simple';
  }

  get _isLastIndex(): boolean {
    return this.lvPageIndex >= this.maxIndex - 1;
  }

  get maxIndex(): number {
    // 从1开始 NEED_DO:0开始？
    return Math.ceil(this.lvTotal / this.lvPageSize);
  }

  get lvPageSizeOptions(): number[] {
    return this._pageSizeOptions || LvConfig.paginatorOptions.lvPageSizeOptions;
  }

  @Input() set lvSelected(value: number) {
    // 已选中条数
    // 总数 大于0
    this._updateSelected(value);
  }

  @Input() set lvTotal(value: number) {
    // 总页数 大于0
    this._updateTotal(value);
    this.setPaginatorState(value);
  }

  @Input() set lvPageSizeOptions(value: number[]) {
    // 指定每页可以显示多少条
    this._pageSizeOptions = (value || LvConfig.paginatorOptions.lvPageSizeOptions).map((item): number =>
      coerceNumberProperty(item),
    );
  }

  previousPage(): void {
    this.jumpToPage(Math.max(this.lvPageIndex, 1));
  }

  ngOnDestroy(): void {
    this._destroy$.next();
    this._destroy$.complete();
  }

  nextPage(): void {
    this.jumpToPage(Math.min(this.lvPageIndex + 2, this.maxIndex));
  }

  ngAfterViewInit(): void {
    // 订阅total change，更新index size
    this._subscribeTotalChange();
  }

  jumpToFisrtPage(): void {
    if (this.lvPageIndex === 0) {
      return;
    }
    this.jumpToPage(1);
  }

  setSelected(value: number | string): void {
    this._updateSelected(value);
    this._cdr.markForCheck();
  }

  _updateSelected(value: number | string): void {
    this._selected = Math.max(coerceNumberProperty(value), 0);
  }

  initData(): void {
    if (!this._initFlag) {
      // 初始化pageSize list
      this._updatePageSizeList();
    }
  }

  onCompositionend(e: CompositionEvent, value: string, target): void {
    // 适配issue2121 在特定环境下无法输入数字问题
    if (Number(e.data).toString() === e.data) {
      return;
    }
    this.setValidValue(value, target, e.data);
  }

  _getNumberList(length: number, start: number = 1): number[] {
    return Array.from({ length }).map((item, key): number => key + start);
  }

  _updateTotal(value: number | string): void {
    this._total = Math.max(coerceNumberProperty(value), 0);
    this.totalChange$.next(this._total);
  }

  _PageSizeChange(index: number): void {
    this.lvPageSize = index;
    this.lvPageIndex = 0;
    this._emitPageChange();
    this._updatePageSizeList();
  }

  _emitPageChange(): void {
    this.lvPageChange.emit({
      pageIndex: this.lvPageIndex,
      pageSize: this.lvPageSize,
      total: this.lvTotal,
    });
  }

  convertOptions(source: any[] = []): Array<{ label: any; isLeaf: true }> {
    return source.map((item): { label: any; isLeaf: true } => ({ label: item, isLeaf: true }));
  }

  ngOnInit(): void {
    this.initData();

    this._codeNumber = this.previewNum * 2 + 1;
    this.panelClass = this.lvPanelClass
      ? `lv-paginator-select-panel ${this.lvPanelClass}`
      : 'lv-paginator-select-panel';
  }

  /**
   * 更新pageIndex
   * 场景：删除项后，pageIndex>maxIndex-1时，自动跳转到最末一页
   */
  _updatePageIndex(): void {
    const maxIndex = this.maxIndex - 1;
    if (this.lvPageIndex > maxIndex && this.lvPageIndex) {
      this.lvPageIndex = Math.max(maxIndex, 0);
      this._emitPageChange();
      this._cdr.markForCheck();
    }
  }

  setValidValue(value: string, target: any, data: string): void {
    const start = target.selectionStart;
    // target.selectionStart在value赋值后会更改，故先保存
    target.value = value.replace(data, '');
    const newStart = start - data.length;
    target.setSelectionRange(newStart, newStart);
  }

  _subscribeTotalChange(): void {
    this.totalChange$
      .pipe(
        distinctUntilChanged(),
        filter((res): boolean => res >= 0),
        takeUntil(this._destroy$),
      )
      .subscribe((): void => {
        this._updatePageIndex();
        this._updatePageSizeList();
      });
  }

  setPaginatorState(val: number = this.lvTotal): void {
    if (TypeUtils.isBoolean(this.lvHideOnSinglePage)) {
      this.showPagination = (this.lvHideOnSinglePage && val > this.lvPageSize) || !this.lvHideOnSinglePage;
    } else {
      this.showPagination = val > (this.lvHideOnSinglePage as number);
    }
  }

  /**
   * 跳转
   * @param value 输入的内容：只支持正整数[1, maxIndex]
   * @param target 元素
   */
  gotoPage(value: string, target: any): void {
    if (value.trim() === '') {
      return;
    }
    const _value = coerceNumberProperty(value);
    let index = parseInt(String(_value), 10);

    // 小于1默认跳转到第一页，大于maxIndex默认跳转到maxIndex
    index = Math.min(Math.max(1, index), this.maxIndex);
    this.jumpToPage(index, target);
  }

  /**
   * 快速跳转
   * @param value 输入的内容: [1, maxIndex]
   * @param target 元素
   */
  jumpToPage(index: number, target?: any): void {
    if (this._total === 0 || this.lvDisabled) {
      return;
    }
    const currentPage = this.lvPageIndex + 1;

    if (index !== currentPage) {
      // 当前页不变
      this.lvPageIndex = index - 1;
      this._emitPageChange();
      // 更新pages
      this._updatePages();
    }

    if (target) {
      target.value = '';
    }
  }

  ngOnChanges(changes: SimpleChanges): void {
    const { lvPageSize, lvTotal, lvPageSizeOptions, lvPageIndex, lvHideOnSinglePage } = changes;
    if (lvPageSize || lvTotal || lvPageSizeOptions) {
      this._initFlag = true;
      this._updatePageSizeList();
    }

    if (lvPageIndex) {
      this._updatePages();
    }

    if (lvHideOnSinglePage || lvPageSize) {
      this.setPaginatorState();
    }
  }

  /**
   * 点击省略号跳转
   */
  quickJump(type): void {
    if (this.lvDisabled) {
      return;
    }

    if (type === 'prev_5') {
      this.lvPageIndex = this.lvPageIndex - this._codeNumber < 0 ? 0 : this.lvPageIndex - this._codeNumber;
    } else {
      this.lvPageIndex =
        this.lvPageIndex + this._codeNumber > this.maxIndex - 1
          ? this.maxIndex - 1
          : this.lvPageIndex + this._codeNumber;
    }

    this._emitPageChange();
    this._updatePages();
  }

  onInput(e: InputEvent, value: string, target: any): void {
    /**
     * 非360浏览器中文输入时
     * 输入会触发一次input，enter键后还会触发一次input,且赋值后会导致12a变成1。具体可参考issue713
     * 故非360浏览器使用onCompositionend处理中文输入，360浏览器不支持onCompositionend
     */
    if (e.inputType === 'insertCompositionText') {
      return;
    }

    // 粘贴时只有全部为数字的才显示
    if (e.inputType === 'insertFromPaste' && isNaN(Number(value))) {
      target.value = '';
    }

    if (isNaN(Number(e.data))) {
      this.setValidValue(value, target, e.data);
    }
  }

  _updatePageSizeList(): void {
    if (!this.lvPageSizeOptions) {
      return;
    }
    this._pageSizeList = [...this.lvPageSizeOptions];
    if (this.lvPageSize <= 0) {
      this.lvPageSize = this._pageSizeList.length ? this._pageSizeList[0] : this._defaultPageSize;
    }
    if (!this._pageSizeList.includes(this.lvPageSize)) {
      this._pageSizeList.push(this.lvPageSize);
    }
    this._pageSizeList.sort((a, b): number => a - b);
    this.pageSizeListOption = this.convertOptions(this._pageSizeList);
    // 更新pages
    this._updatePages();
  }

  // _renderPages默认不包含最后一页
  _updatePages(): void {
    const pages: number[] = [];
    const { maxIndex } = this;

    let current = this.lvPageIndex + 1;
    this.renderStartNum = 2;
    this.renderEndNum = maxIndex - 1;

    // 判断当前页是否在首尾页的区间
    if (current < 1) {
      current = 1;
    }
    if (current > maxIndex) {
      current = maxIndex;
    }

    // 判断当前页与首页、尾页的关系
    if (current <= this.previewNum + 2) {
      this.renderStartNum = 2;
    } else if (current >= maxIndex - this.previewNum) {
      this.renderStartNum = maxIndex - this.previewNum * 2;
      if (this.renderStartNum < 2) {
        this.renderStartNum = 2;
      }
    } else {
      this.renderStartNum = current - this.previewNum;
    }

    if (current >= maxIndex - this.previewNum - 1) {
      this.renderEndNum = maxIndex - 1;
    } else if (current <= this.previewNum + 1) {
      this.renderEndNum = this.previewNum * 2 + 1;
      if (this.renderEndNum > maxIndex - 1) {
        this.renderEndNum = maxIndex - 1;
      }
    } else {
      this.renderEndNum = current + this.previewNum;
    }

    for (let i = this.renderStartNum; i < this.renderEndNum + 1; i++) {
      pages.push(i);
    }

    this._renderPages = pages;
    // 精简分页只需拿到maxIndex即可获取option，无需等待current计算完成后再获取，提高效率
    // NEED_DO: 精简模式下大数据奔溃采用虚拟滚动+scrollEnd追加数据
    if (this.lvMode === 'simple') {
      this.pagesOption = this.convertOptions(this._getNumberList(maxIndex));
    }

    this._cdr.markForCheck();
  }
}
